﻿using System;
using System.Collections.Generic;
using log4net;

namespace Mistral.Utils
{
	public class TextResolver
	{
		private static readonly ILog __log = LogManager.GetLogger(typeof (TextResolver));
		private string _originalText;

		public TextResolver(string _originalText)
		{
			this._originalText = _originalText;
		}

		public string OriginalText
		{
			get { return _originalText; }
			set { _originalText = value; }
		}

		public string Resolve(params IDictionary<string, string>[] dataBlocks)
		{
			string result = _originalText;

			// Ищем индекс начала переменной
			int index = _originalText.IndexOf("%");
			while (index >= 0)
			{
				// Вычленяем имя переменной
				int index2 = result.IndexOf("%", index + 1);
				if (index2 < 0)
					break;

				// Имя переменной
				string varName = result.Substring(index + 1, index2 - index - 1);
				string fullVarName = "%" + varName + "%";

				// Получение значения
				string value = GetData(dataBlocks, varName);

				// Значение переменной равно тексту, ищем в родительских блоках
				IDictionary<string, string>[] prevBlocks = dataBlocks;
				while (value == fullVarName && prevBlocks.Length > 1)
				{
					// Блоки данных исключая текущий
					IDictionary<string, string>[] blocks = new IDictionary<string, string>[prevBlocks.Length - 1];
					Array.Copy(prevBlocks, 1, blocks, 0, blocks.Length);

					// Получение значения
					value = GetData(blocks, varName);

					// Дальше...
					prevBlocks = blocks;
				}

				// Если значение получено
				if (value != null)
				{
					// Заменяем в тексте
					result = result.Replace( fullVarName, value );
				}
				else
				{
					__log.ErrorFormat("Значение {0} не найдено", varName);

					// Пропускаем неразобранное значение
					index = index2 + 1;
					if (index >= result.Length - 1)
						break;
				}

				// Ищем следующую переменную
				index = result.IndexOf("%", index);
			}

			return result;
		}

		private static string GetData(IDictionary<string, string>[] blocks, string name)
		{
			string result = null;
			for (int i = 0; i < blocks.Length; i++)
			{
				if (blocks[i].TryGetValue(name, out result))
					break;
			}
			return result;
		}
	}
}